package demo.designPattern.aop.aspectJ.aspect;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;

/**
 * 除了熟悉的基于代码的切面声明风格外，AspectJ 5 还支持基于注解的切面声明风格。
 * 我们非正式地称支持这种开发风格的一组注解为 "@AspectJ" 注解。
 *
 * <p>
 * AspectJ 5 支持在切面上以及切面内部的方法、字段、构造函数、通知和类型引入声明上使用注解。
 * 方法和通知参数也可以被注解。切点声明或声明语句上不允许使用注解。
 *<a href="https://eclipse.dev/aspectj/doc/released/adk15notebook/annotations-aspectmembers.html">参考</a>
 * 以下示例说明了在切面中使用注解的情况：
 * <blockquote><pre>
 *
 * #@AspectAnnotation
 * public abstract aspect ObserverProtocol {
 *
 *            #@InterfaceAnnotation
 *            interface Observer {}
 *
 *            #@InterfaceAnnotation
 *            interface Subject {}
 *
 *            #@ITDFieldAnnotation
 *            private List<Observer> Subject.observers;
 *
 *            #@ITDMethodAnnotation
 *            public void Subject.addObserver(Observer o) {
 * 			  observers.add(o);
 *            }
 *
 *            #@ITDMethodAnnotation
 *            public void Subject.removeObserver(Observer o) {
 * 			  observers.remove(o);
 *            }
 *
 *            #@MethodAnnotation
 *            private void notifyObservers(Subject subject) {
 * 			  for(Observer o : subject.observers)
 * 			    notifyObserver(o,subject);
 *            }
 *
 *
 * 			//Delegate to concrete sub-aspect the actual form of notification for a given type of Observer.
 *            #@MethodAnnotation
 *            protected abstract void notifyObserver(Observer o, Subject s);
 *
 * 			// no annotations on pointcuts
 * 			protected abstract pointcut observedEvent(Subject subject);
 *
 *            #@AdviceAnnotation
 *            after(Subject subject) returning : observedEvent(subject) {
 * 				notifyObservers(subject);
 *            }
 *        }
 *
 * </pre></blockquote>
 */
@Aspect
public class SecuredMethodAspect {
    @Pointcut("@annotation(secured)")
    public void callAt(Secured secured) {
    }

    /**
     *
     * @param pjp
     * @param secured
     * @return
     * @throws Throwable
     */
    @Around("callAt(secured)")
    public Object around(ProceedingJoinPoint pjp,
                         Secured secured) throws Throwable {
        return secured.isLocked() ? null : pjp.proceed();
    }
}
